package org.boulderfoodrescue.webapp.client.pickuptimes.timepicker;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.boulderfoodrescue.webapp.client.resources.Resources;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.MouseOverEvent;
import com.google.gwt.event.dom.client.MouseOverHandler;
import com.google.gwt.event.logical.shared.HasValueChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.event.shared.SimpleEventBus;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTMLTable.Cell;
import com.google.gwt.user.client.ui.HTMLTable.RowFormatter;
import com.google.gwt.user.client.ui.HasValue;
import com.google.gwt.user.client.ui.ScrollPanel;

public class TimeTable extends FlowPanel implements HasValue<Time>, HasValueChangeHandlers<Time>{
	private FlexTable table;
	private ScrollPanel sPanel;
	private RowFormatter rf;
	private EventBus bus = new SimpleEventBus();
	private Time value;
	private Integer selected_row;
	private Map<Integer, Time> map = new HashMap<Integer, Time>();
	public TimeTable(Time start_time, Time end_time, int interval){
		table = new FlexTable();
		rf = table.getRowFormatter();
		String styleName = Resources.INSTANCE.timepicker().table_row();
		int j = 0;
		for(int i=start_time.getMinuteCount();i<end_time.getMinuteCount();i+=interval)
		{
			Time t = new Time(i/60, i%60);
			if(j == 0)
				value = t;
			table.setText(j, 0, t.toStringTimeShort());
			map.put(j, t);
			rf.setStyleName(j, styleName);
			++j;
		}
		table.addClickHandler(new ClickHandler(){
			@Override
			public void onClick(ClickEvent event) {
				Cell cell = table.getCellForEvent(event);
				if(cell != null){
					int row = cell.getRowIndex();
					setValue(map.get(row),true);
				}
			}
		});
		table.addDomHandler(new MouseOverHandler(){
			@Override
			public void onMouseOver(MouseOverEvent event) {
				if(selected_row != null)
					rf.removeStyleName(selected_row, Resources.INSTANCE.timepicker().selected_row());
				selected_row = null;
			}
		}, MouseOverEvent.getType());

		sPanel = new ScrollPanel(table);
		sPanel.setHeight("150px");
		sPanel.setWidth("7em");
		this.add(sPanel);
	}

	public void onShow(Time current){
		value = current;
		if(selected_row != null)
			rf.removeStyleName(selected_row, Resources.INSTANCE.timepicker().selected_row());
		selected_row = null;
		Iterator<Entry<Integer, Time>> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Entry<Integer, Time> pairs = (Entry<Integer, Time>)it.next();
			if(pairs.getValue().getMinuteCount()==value.getMinuteCount()){
				selected_row = pairs.getKey();
				rf.setStyleName(selected_row, Resources.INSTANCE.timepicker().selected_row());
				break;
			}
		}
		if(table.getOffsetHeight()>0 && selected_row != null){
			int sizeOfRow = table.getOffsetHeight()/table.getRowCount();
			sPanel.setVerticalScrollPosition(selected_row*sizeOfRow);
		}
	}

	@Override
	public void fireEvent(GwtEvent<?> event){
		bus.fireEvent(event);
	}

	@Override
	public HandlerRegistration addValueChangeHandler(
			ValueChangeHandler<Time> handler) {
		return bus.addHandler(ValueChangeEvent.getType(), handler);
	}

	@Override
	public Time getValue() {
		return value;
	}

	@Override
	public void setValue(Time value) {
		setValue(value, true);
	}

	@Override
	public void setValue(Time value, boolean fireEvents) {
		if(value == null)
			return;
		Iterator<Entry<Integer, Time>> it = map.entrySet().iterator();
		while (it.hasNext()) {
			Entry<Integer, Time> pairs = (Entry<Integer, Time>)it.next();
			if(pairs.getValue().getMinuteCount() >= value.getMinuteCount()){
				setValue(value, pairs.getKey(), fireEvents);
				return;
			}
		}
		setValue(value, 0, fireEvents);
	}

	public void setValue(Time value, Integer row, boolean fireEvents){
		this.value = value;
		if(fireEvents)
			ValueChangeEvent.fire(this, value);
		String styleName = Resources.INSTANCE.timepicker().selected_row();
		rf.addStyleName(row, styleName);
		if(selected_row != null)
			rf.removeStyleName(selected_row, styleName);
		selected_row = row;
	}
	public void up() {
		if(selected_row != null && table.getRowCount() < selected_row)
			setValue(map.get(selected_row+1), selected_row+1, false);
		else
			setValue(map.get(0), 0, false);
	}
	public void down() {
		if(selected_row != null && selected_row > 0)
			setValue(map.get(selected_row-1), selected_row-1, false);
		else
			setValue(map.get(table.getRowCount()), table.getRowCount(), false);

	}
}
